﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Soundelle.Oscillator
{
    public class GeneratorRandom : BaseDevice
    {
        public GeneratorRandom()
        {
        }

        private ParameterType[] _AvailableParameters = { 
            ParameterType.Parameter_DC_Offset,
            ParameterType.Parameter_Amplitude,
            ParameterType.Parameter_IsZeroPeak,
            ParameterType.Parameter_Distribution,
            ParameterType.Parameter_Averages
        };
        override public ParameterType[] AvailableParameters
        {
            get
            { return _AvailableParameters; }
        }

        private DeviceFunctionType[] _AvailableFunctions = new DeviceFunctionType[] {
             DeviceFunctionType.Function_GeneratorRandom
        };
        override public DeviceFunctionType[] AvailableFunctions
        {
            get
            { return _AvailableFunctions; }
        }
 
        override protected void InitRmsRatio()
        {
            //RMS( rnd(1)^N ) = 1 / (2N + 1)^2
            RmsRatio = 1.0 / Math.Pow((2.0 * Parameter_Distribution + 1.0),2.0);
        }

        override public void Reset()
        {
            string guidStr =  GUID.ToString().Replace("-","");
            int id = 0;
            for (int i = 0; i < 8; ++i)
            {
                id += Convert.ToInt32(guidStr.Substring(i * 4, 4), 16);
            }

            rnd = new Random(id);
            base.Reset();
        }

        Random rnd = new Random();
        override public double SignalOut()
        {
            if (!Enabled)
                return 0.0;

            double signalOut = 0.0;
            double signalIn = 0.0;

            double DcOffset =Parameter_DC_Offset;
            double amplitude = Parameter_Amplitude;
            double frequency = Parameter_Frequency;
            double phase = Parameter_Phase;
            double duty = Parameter_Duty;

            double distribution = Parameter_Distribution;
            long averages = Parameter_Averages;

            DoModulationByChildDevices(ref signalOut, ref signalIn, ref amplitude, ref frequency, ref phase, ref duty);

            //----

            double sig = 0.0;
            
            if (averages < 1)
                averages=1;

            for (int i=0; i<averages; ++i)
            {
                sig += amplitude * Math.Pow(rnd.NextDouble(), distribution);
            }
            sig /=averages;

            if (!Parameter_IsZeroPeak)
            {
                int sign = rnd.Next(100);
                if (sign < 50)
                    sig = -sig;
            }

            ++TimePosition;
            double SignalOut = sig + amplitude * signalIn + signalOut + DcOffset;
            SetPreviousSignalOut(SignalOut);
            return SignalOut;
        }
    }
}
